package xyz.nanzhou.needDemo02;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import xyz.nanzhou.needDemo02.util.FtpUtil;


import java.io.*;
import java.net.Socket;
import java.util.concurrent.*;

/**
 * @title:
 * @author:nanzhou
 * @date:
 */
public class NeedTest02 {
    public static void main(String[] args) throws InterruptedException {
        //线程池创建
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(2, Integer.MAX_VALUE, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
        //请求累加器
        int n = 1;

//        while (true) {
            System.out.println("\n\n第" + (n++) + "次请求");
            //启动服务线程
            poolExecutor.submit(new pingRunnable());
            //休眠1分钟
            Thread.sleep(6000);
//        }

    }
}

/**
 * 服务主要任务
 */
class pingRunnable implements Runnable {

    @Override
    public void run() {
        //建立分支线程池
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(2, Integer.MAX_VALUE, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
        //读取目标 json 文件
        File file = new File("src/xyz/nanzhou/needDemo02/testsource/info.json");
        //启动分支线程
        try (FileInputStream fileInputStream = new FileInputStream(file);) {
            BufferedReader br = new BufferedReader(new InputStreamReader(fileInputStream, "utf-8"));
            //数据流
            String line = null;
            String data = "";

            while ((line = br.readLine()) != null) {
                data += line;
            }
            //解析 json 文件
            JSONObject jsonObject = JSON.parseObject(data);
            //解析为 json 数组
            JSONArray websites = jsonObject.getJSONArray("websites");
            //计数器
            int n = 0;
            for (int i = 0; i < websites.size(); i++) {
                //获取 json 数据
                JSONObject website = websites.getJSONObject(i);
                //创建分支任务对象
                PingCallble pingCallble = new PingCallble();

                //读取 信息
                String name = website.getString("name");
                String url = website.getString("url");
                String username = website.getString("username");
                String password = website.getString("password");
                String localFilePath = website.getString("localFilePath");
                String remoteFilePath = website.getString("remoteFilePath");
                //设置 分支数据
                pingCallble.setName(name);
                pingCallble.setUrl(url);
                pingCallble.setHost(url);
                pingCallble.setUsername(username);
                pingCallble.setPassword(password);
                pingCallble.setRemoteFilePath(remoteFilePath);
                pingCallble.setLocalFilePath(localFilePath);
//                pingCallble.
                //创建接收数据的 FutureTask
                FutureTask<Integer> futureTask = new FutureTask<>(pingCallble);
                //启动分支线程
                poolExecutor.submit(futureTask);

                //计数器累加
                n +=futureTask.get();
            }
            //输出任务结果
            System.out.println("\n本次OK: " + n + "次\n本次ERROR: " + (websites.size() - n) + "\n成功率： " + ((double) n / websites.size() * 100) + "%");
        } catch (ExecutionException | InterruptedException | IOException e) {
            throw new RuntimeException(e);
        }
    }
}

/**
 * 服务分支任务
 */
class PingCallble implements Callable<Integer> {
    //任务数据信息
    private String name = "";
    private String url = "";
    private String host ;
    private static int port = 21;
    private String username ;
    private String password;
    private String localFilePath ;
    private String remoteFilePath;

    //设置数据
    public void setName(String name) {
        this.name = name;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setLocalFilePath(String localFilePath) {
        this.localFilePath = localFilePath;
    }

    public void setRemoteFilePath(String remoteFilePath) {
        this.remoteFilePath = remoteFilePath;
    }

    /**
     * 进行判断服务器是否正常运行
     *
     * @return 运行信息
     * @throws Exception
     */
    @Override
    public Integer call() throws Exception {
        //接收 服务器访问信息
        String temp = iserver(url);
        //成功计数器
        int n = 0;
        //返回值判断
        if (Integer.parseInt(temp.split(" ")[0]) == 200) {
            //输出分支任务结果
            System.out.println(name + "\t(" + url + ")\t" + temp);
            //uploadFile
            uploadFile();

            n++;
        } else {
            temp = "ERROR " + temp.split(" ")[1];
        }
        return n;
    }

    /**
     * 上传文件
     */
    private void uploadFile() {
        FtpUtil ftpUtil = new FtpUtil();
        if (ftpUtil.connect(url, port, username, password)) {
            // 上传文件
            if (ftpUtil.uploadFile(localFilePath, remoteFilePath)) {
                System.out.println("上传成功");
            } else {
                System.out.println("上传失败");
            }
            ftpUtil.disconnect();
        } else {
            System.out.println("连接失败");
        }
    }



    /**
     * 获取运行响应码以及字节访问速度
     *
     * @param s 访问地址
     * @return 返回运行响应码以及字节访问速度
     */
    private static String iserver(String s) {

        //处理 url
        if (s.contains("://")){
            s = s.split("://")[1];
        }

        try (Socket socket = new Socket(s, 80);
             BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
        ) {
            // 记录开始时间
            long startTime = System.currentTimeMillis();
            //请求
            out.println("GET / HTTP/1.1");
            out.println("Host: " + s);
            out.println("Connection: Close");
            out.println();
            //读取响应数据
            String statusLine = in.readLine();
            statusLine = statusLine.split(" ")[1];
            // 记录结束时间
            long endTime = System.currentTimeMillis();

            // 计算访问速度（单位为字节/秒）
            double speed = (double) (endTime - startTime) / statusLine.length();

            return String.format("%s %.2f秒", statusLine, speed);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
